#pragma once

#ifndef _CLUAMANAGER_H_
#define _CLUAMANAGER_H_

extern "C"
{
   #include "LUA/lua.h"
   #include "LUA/lauxlib.h"
   #include "LUA/lualib.h"
}

#include "CChar.h"
#include "CNpc.h"
#include "CSpell.h"
#include "CTradeContainer.h"
#include "CConsole.h"
#include "CZoneHandler.h"
#include "CEventPacket.h"
#include "CSemaphore.h"

#include "CSimpleEventPacket.h"
#include "CAbility.h"

class CShopBuyMenuPacket;

// Lua functions forward declaration
int l_getNPCName(		lua_State* luaVM);
int l_getNPCId(			lua_State* luaVM);


int l_getNPCById(		lua_State* luaVM);
int l_getNPCByTargId(	lua_State* luaVM);

int l_getNPCState( lua_State* luaVM, CBaseEntity * pEntity );
int l_setNPCState( lua_State* luaVM, CBaseEntity * pEntity );

int l_getFamilyId( lua_State* luaVM, CBaseEntity * pEntity );

int l_setNPCAnimation(	lua_State* luaVM);

int l_showNPCTextLine( lua_State* luaVM, CBaseEntity * pEntity );

int l_getCharName(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getCharId(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getCharJob(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getCharLvl(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getCharSubJob(		lua_State* luaVM, CBaseEntity * pEntity);
int l_getCharSubLvl(		lua_State* luaVM, CBaseEntity * pEntity);

int l_getCharRace(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getCharNation(		lua_State* luaVM, CBaseEntity * pEntity);

int l_getCharHp(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getCharMp(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getTp(				lua_State* luaVM, CBaseEntity * pEntity);
int l_getCharXPos(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getCharYPos(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getCharZPos(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getCharRotation(		lua_State* luaVM, CBaseEntity * pEntity);
int l_getCharZone(			lua_State* luaVM, CBaseEntity * pEntity);

int l_getCharVar(			lua_State* luaVM, CBaseEntity * pEntity);
int l_setCharVar(			lua_State* luaVM, CBaseEntity * pEntity);

int l_getWeaponDelay(			lua_State* luaVM, CBaseEntity * pEntity);


int l_getCharPrevZone(	lua_State* luaVM, CBaseEntity * pEntity);
int l_getCharCurrGil(	lua_State* luaVM, CBaseEntity * pEntity);
int l_gainGil(			lua_State* luaVM, CBaseEntity * pEntity);
int l_removeGil(		lua_State* luaVM, CBaseEntity * pEntity);

int l_learnWs(		lua_State* luaVM, CBaseEntity * pEntity);
int l_addSpell(		lua_State* luaVM, CBaseEntity * pEntity);
int l_hasSpell(		lua_State* luaVM, CBaseEntity * pEntity);


int l_sendTractor(lua_State* luaVM, CBaseEntity * pEntity);
int l_sendRaise(lua_State* luaVM, CBaseEntity * pEntity);

// SHOP CREATION FUNCTIONS
int l_createShop(		lua_State* luaVM, CBaseEntity * pEntity);
int l_shopAddItem(		lua_State* luaVM, CShopBuyMenuPacket * pShopBuyMenu);
int l_sendShop(			lua_State* luaVM, CBaseEntity * pEntity);
int l_sendGuild(		lua_State* luaVM, CBaseEntity * pEntity);

// SKILL VALUES AND RANKS FUNCTIONS
int l_getSkill(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getSkillRank(		lua_State* luaVM, CBaseEntity * pEntity);
int l_setSkillRank(		lua_State* luaVM, CBaseEntity * pEntity);

// EVENT CREATION FUNCTIONS

int l_createEvent(		lua_State* luaVM);
int l_setEventParams(	lua_State* luaVM, CEventPacket * pEvent);
int l_setEventCallbackFunc(		lua_State* luaVM, CEventPacket * pEvent);
int l_setEventCallbackFile(		lua_State* luaVM, CEventPacket * pEvent);
int l_startEvent(lua_State* luaVM, CBaseEntity * pEntity);

int l_sendMoreEvent(	lua_State* luaVM, CBaseEntity * pEntity);
int l_sendRelease(		lua_State* luaVM, CBaseEntity * pEntity);

int l_charUnlockSubjobs(lua_State* luaVM, CBaseEntity * pEntity);
int l_charUnlockJob(	lua_State* luaVM, CBaseEntity * pEntity);

int l_getFreeSlotCount(	lua_State* luaVM, CBaseEntity * pEntity);

int l_sendSpecialMessage(lua_State* luaVM, CBaseEntity * pEntity);

int l_addQuest(			lua_State* luaVM, CBaseEntity * pEntity);
int l_completeQuest(	lua_State* luaVM, CBaseEntity * pEntity);
int l_getQuestStatus(	lua_State* luaVM, CBaseEntity * pEntity);
int l_currentMission(	lua_State* luaVM, CBaseEntity * pEntity);
int l_completeMission(	lua_State* luaVM, CBaseEntity * pEntity);
int l_getMissionStatus(	lua_State* luaVM, CBaseEntity * pEntity);

int l_setLevelCap(		lua_State* luaVM, CBaseEntity * pEntity);
int l_getLevelCap(		lua_State* luaVM, CBaseEntity * pEntity);

int l_setTitle(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getTitle(			lua_State* luaVM, CBaseEntity * pEntity);

int l_spawnPet(			lua_State* luaVM, CBaseEntity * pEntity);

int l_getAtt(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getAcc(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getDef(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getEva(			lua_State* luaVM, CBaseEntity * pEntity);

int l_setFame(	lua_State* luaVM, CBaseEntity * pEntity );
int l_addFame(	lua_State* luaVM, CBaseEntity * pEntity );
int l_getFame(	lua_State* luaVM, CBaseEntity * pEntity );
int l_getFameLevel(	lua_State* luaVM, CBaseEntity * pEntity );

int l_getCharRank(			lua_State* luaVM, CBaseEntity * pEntity);
int l_charRankUp(			lua_State* luaVM, CBaseEntity * pEntity );
int l_getCharRankPoints(	lua_State* luaVM, CBaseEntity * pEntity);
int l_addCharRankPoints(	lua_State* luaVM, CBaseEntity * pEntity );

int l_getEquip(lua_State* luaVM, CBaseEntity * pEntity );

int l_getGlobalVar(		lua_State* luaVM);

int l_setGlobalVar(		lua_State* luaVM);

int l_spawnMob(		lua_State* luaVM, CZone * pZone);

int l_warpChar(lua_State* luaVM, CBaseEntity * pEntity );

int l_updateEnmity(lua_State* luaVM, CBaseEntity * pEntity );

int l_getVModifier(lua_State* luaVM, CBaseEntity * pEntity );
int l_getCModifier(lua_State* luaVM, CBaseEntity * pEntity );

int l_getTradeGil(		lua_State* luaVM, CTradeContainer * pItems );
int l_getItemID(		lua_State* luaVM, CTradeContainer * pItems );
int l_getItemQuantity(	lua_State* luaVM, CTradeContainer * pItems );
int l_getSlotQuantity(	lua_State* luaVM, CTradeContainer * pItems );
int l_getItemCount(		lua_State* luaVM, CTradeContainer * pItems );
int l_hasItemQuantity(	lua_State* luaVM, CTradeContainer * pItems );
int l_tradeComplete(	lua_State* luaVM, CTradeContainer * pItems );

int l_setCharCurrGil(	lua_State* luaVM, CBaseEntity * pEntity );
int l_setCharZone(		lua_State* luaVM);
int l_setCharPos(		lua_State* luaVM, CBaseEntity * pEntity );
int l_setCharHomePoint(	lua_State* luaVM, CBaseEntity * pEntity );
int l_setCharAnimation(	lua_State* luaVM, CBaseEntity * pEntity );
int l_setCharNation(	lua_State* luaVM, CBaseEntity * pEntity );

int l_setCharFameSan(	lua_State* luaVM, CBaseEntity * pEntity );
int l_setCharFameBas(	lua_State* luaVM, CBaseEntity * pEntity );
int l_setCharFameWin(	lua_State* luaVM, CBaseEntity * pEntity );
int l_setCharFameNorg(	lua_State* luaVM, CBaseEntity * pEntity );

int l_getTarget(		lua_State* luaVM, CBaseEntity * pEntity);


int l_getElementalResist(lua_State* luaVM, CBaseEntity * pEntity);
int l_getStat(			lua_State* luaVM, CBaseEntity * pEntity);

int l_isPlayer(			lua_State* luaVM, CBaseEntity * pEntity);
int l_isNPC(			lua_State* luaVM, CBaseEntity * pEntity);
int l_isMob(			lua_State* luaVM, CBaseEntity * pEntity);

int l_CharAddItem(		lua_State* luaVM, CBaseEntity * pEntity);
int l_CharAddAndEquipItem(lua_State* luaVM, CBaseEntity * pEntity);
int l_CharGetItemInfo(	lua_State* luaVM, CBaseEntity * pEntity);
int l_CharHasItem(		lua_State* luaVM, CBaseEntity * pEntity);
int l_CharTakeItem(		lua_State* luaVM, CBaseEntity * pEntity);

int l_increaseStorage(	lua_State* luaVM, CBaseEntity * pEntity);

int l_addKeyItem(		lua_State* luaVM, CBaseEntity * pEntity);
int l_hasKeyItem(		lua_State* luaVM, CBaseEntity * pEntity);
int l_seenKeyItem(		lua_State* luaVM, CBaseEntity * pEntity);
int l_removeKeyItem(	lua_State* luaVM, CBaseEntity * pEntity);

int l_setHp(			lua_State* luaVM, CBaseEntity * pEntity);

int l_setAbilityMessage(lua_State* luaVM, CAbility * pAbi);
int l_setAbilityResult(	lua_State* luaVM, CAbility * pAbi);

int l_setItemMessage(	lua_State* luaVM, CItem * pItem);
int l_setItemAnimation(	lua_State* luaVM, CItem * pItem);
int l_setItemRemove(	lua_State* luaVM, CItem * pItem);

int l_setMp(			lua_State* luaVM, CBaseEntity * pEntity);
int l_setTp(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getMaxHp(			lua_State* luaVM, CBaseEntity * pEntity);
int l_getMaxMp(			lua_State* luaVM, CBaseEntity * pEntity);
int l_addHp(			lua_State* luaVM, CBaseEntity * pEntity);
int l_addMp(			lua_State* luaVM, CBaseEntity * pEntity);
int l_removeHp(			lua_State* luaVM, CBaseEntity * pEntity);
int l_removeMp(			lua_State* luaVM, CBaseEntity * pEntity);

int l_getBaseDamage(	lua_State* luaVM, CBaseEntity * pEntity);

int l_getMPCost(lua_State* luaVM, CSpell* spell);
int l_getSpellElement(lua_State* luaVM, CSpell* spell);
int l_setMsg(lua_State* luaVM, CSpell* spell);
int l_getCurrentSpellTargetNum(lua_State* luaVM, CSpell* spell);
int l_getSpellTargetNum(lua_State* luaVM, CSpell* spell);

int l_getVanaYear(		lua_State* luaVM);
int l_getVanaMonth(		lua_State* luaVM);
int l_getVanaDayElement(lua_State* luaVM);
int l_getVanaDay(		lua_State* luaVM);
int l_getVanaHour(		lua_State* luaVM);
int l_getVanaMinute(	lua_State* luaVM);

int l_registerRegion(	lua_State* luaVM);

int l_sendTellMsg(		lua_State* luaVM);

int l_executeSQL(		lua_State* luaVM);

int l_sendMenu(			lua_State* luaVM, CBaseEntity * pEntity);

int l_getZone(			lua_State*);
int l_getWeather(		lua_State* luaVM, CZone * pZone);

int l_setAbilityAnimation(lua_State* luaVM, CAbility * pAbi);
int l_setSpellAnimation(lua_State* luaVM, CSpell * pSpell);

inline LUA_API lua_Number lua_popnumber(lua_State *L);

inline LUA_API const char *lua_popstring(lua_State *L);



class CLuaManager
{
private:
	CLuaManager(void);
	~CLuaManager(void);
	static lua_State* m_state;
	static CSemaphore m_LuaState;
public:
	static int  Initialize();
	static bool scriptExists(char * filename);
	static void OnServerStart();
	static void OnTrigger( CChar * schar, CBaseEntity * npc);
	static void OnEventSelection(CChar * schar, int eventID, int result);
	static void OnEventFinish(CChar * schar, int eventID, int result);
	static int	OnZoneIn(CChar * schar, int prevzone);
	static void OnCharCreate(CChar * schar);
	static void OnZoneInitialize(int zoneID);
	static void OnRegionEnter(CChar * schar, int regionID);
	static void OnTrade(CChar * schar, CBaseEntity * npc, CTradeContainer * tradeItems);
	static void OnSpellCastFinish(CChar * schar, CSpell * spell);
	static int  OnSpellCast(CChar * schar, CSpell * spell);
	static int  OnUseWeaponSkill(CChar * schar, CBaseEntity * target, int wsID);
	static int  OnUseAbility(CChar * schar, CBaseEntity * target, CAbility * pAbility, bool isFirstTarget = false);
	static int	OnUseItem(CChar * schar, CBaseEntity * target, CItem * pItem);
	static std::vector<struct regions> regionList[256]; 
};



#endif